package com.wzz.common.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Date;

import android.os.Environment;
import android.util.Log;

public class LogUtil {
  final static String TAG = LogUtil.class.getSimpleName();
  // public final static boolean LOG_ENABLED = true;

  final static int LOGCAT_LEVEL = 2;// logcat level
  final static int FILE_LOG_LEVEL = 16;// log file level, must >= LOGCAT_LEVEL

  final static int LOG_LEVEL_ERROR = 16;
  final static int LOG_LEVEL_WARN = 8;
  final static int LOG_LEVEL_INFO = 4;
  final static int LOG_LEVEL_DEBUG = 2;

  public final static boolean DEBUG = (LOGCAT_LEVEL <= LOG_LEVEL_DEBUG);
  public final static boolean INFO = (LOGCAT_LEVEL <= LOG_LEVEL_INFO);
  public final static boolean WARN = (LOGCAT_LEVEL <= LOG_LEVEL_WARN);
  public final static boolean ERROR = (LOGCAT_LEVEL <= LOG_LEVEL_ERROR);

  final static String LOG_FILE_NAME = "audio_class.log";

  private final static String LOG_TAG_STRING = "AUDIO";

  final static String LOG_ENTRY_FORMAT = "[%tF %tT][%s][%s]%s"; // [2010-01-22
                                                                // 13:39:1][D][com.bbt.sm]error
                                                                // occured
  static PrintStream logStream;

  static boolean initialized = false;

  public static void d(String tag, String msg) {
    if (DEBUG) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.d(LOG_TAG_STRING, tag + " : " + msg);
      if (FILE_LOG_LEVEL <= LOG_LEVEL_DEBUG)
        write("D", tag, msg, null);
    }
  }

  public static void d(String tag, String msg, Throwable error) {
    if (DEBUG) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.d(LOG_TAG_STRING, tag + " : " + msg, error);
      if (FILE_LOG_LEVEL <= LOG_LEVEL_DEBUG)
        write("D", tag, msg, error);
    }
  }

  public static void i(String tag, String msg) {
    if (INFO) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.i(LOG_TAG_STRING, tag + " : " + msg);
      if (FILE_LOG_LEVEL <= LOG_LEVEL_INFO)
        write("I", tag, msg, null);
    }
  }

  public static void i(String tag, String msg, Throwable error) {
    if (INFO) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.i(LOG_TAG_STRING, tag + " : " + msg, error);
      if (FILE_LOG_LEVEL <= LOG_LEVEL_INFO)
        write("I", tag, msg, error);
    }
  }

  public static void w(String tag, String msg) {
    if (WARN) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.w(LOG_TAG_STRING, tag + " : " + msg);
      if (FILE_LOG_LEVEL <= LOG_LEVEL_WARN)
        write("W", tag, msg, null);
    }
  }

  public static void w(String tag, String msg, Throwable error) {
    if (WARN) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.w(LOG_TAG_STRING, tag + " : " + msg, error);
      if (FILE_LOG_LEVEL <= LOG_LEVEL_WARN)
        write("W", tag, msg, error);
    }
  }

  public static void e(String tag, String msg) {
    if (ERROR) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.e(LOG_TAG_STRING, tag + " : " + msg);

      if (FILE_LOG_LEVEL <= LOG_LEVEL_ERROR)
        write("E", tag, msg, null);
    }
  }

  public static void e(String tag, String msg, Throwable error) {
    if (ERROR) {
      tag = Thread.currentThread().getName() + ":" + tag;
      Log.e(LOG_TAG_STRING, tag + " : " + msg, error);

      if (FILE_LOG_LEVEL <= LOG_LEVEL_ERROR)
        write("E", tag, msg, error);
    }
  }

  private static void write(String level, String tag, String msg, Throwable error) {
    if (!initialized)
      init();
    if (logStream == null || logStream.checkError()) {
      initialized = false;
      return;
    }
    Date now = new Date();
    logStream.printf(LOG_ENTRY_FORMAT, now, now, level, tag, msg);
    logStream.println();

    if (error != null) {
      error.printStackTrace(logStream);
      logStream.println();
    }
  }

  public static synchronized void init() {
    if (initialized)
      return;
    try {
      File sdRoot = getSDRootFile();
      if (sdRoot != null) {
        File logFile = new File(sdRoot, LOG_FILE_NAME);
        logFile.createNewFile();

        Log.d(LOG_TAG_STRING, TAG + " : Log to file : " + logFile);
        if (logStream != null) {
          logStream.close();
        }
        logStream = new PrintStream(new FileOutputStream(logFile, true), true);
        initialized = true;
      }
    } catch (Exception e) {
      Log.e(LOG_TAG_STRING, "init log stream failed", e);
    }
  }

  public static boolean isSdCardAvailable() {
    return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
  }

  public static File getSDRootFile() {
    if (isSdCardAvailable()) {
      return Environment.getExternalStorageDirectory();
    } else {
      return null;
    }
  }

  @Override
  protected void finalize() throws Throwable {
    super.finalize();
    if (logStream != null)
      logStream.close();
  }

}
